the inefficent loop
This loop runs through the netcdf files and then looks for which rows in data_aea it should extract the value to point from, and at what depth (netcDF layer)
Start with 2007_10 data
strt <- Sys.time() #get the start time
xy <- testbk190000[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbk190000sp <- SpatialPointsDataFrame(coords = xy, data = testbk190000, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 2007 # a variable for the observation year
mth <- 10 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbk190000sp)) {
de <- testbk190000sp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbk190000sp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$temp_depth[j] <- NA
} else
testbk190000sp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbk190000sp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$salinity_depth[j] <- NA
} else
testbk190000sp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbk190000sp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$chl_depth[j] <- NA
} else
testbk190000sp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbk190000sp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
if (is.na(de)){
testbk190000sp$o2_depth[j] <- NA
} else
testbk190000sp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbk190000sp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbk190000sp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbk190000sp[j, ])
}
}
}
[1] "2007_10_chl.nc"
ok now create the first lot of random for 2007_10
testbk100001999 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200001999 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300001999 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500001999 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000001999 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900001999 <- test_back_df[sample(nrow(test_back_df), 190000), ]
plot each variable against the different no of background points
ggplot(test10000, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/ssh_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/mlp_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/temp_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/salinity_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/chl_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_surface_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

ggplot(test10000, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=test20000 , na.rm = TRUE, colour = "blue") + geom_density(data=test50000 , na.rm = TRUE, colour = "green") + geom_density(data=test100000 , na.rm = TRUE, colour = "orange") + geom_density(data=test190000 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../data/o2_depth_back_no.png") # to automatically save the plot to a png AND show it inline
png
3
dev.off() # stops automatic saving of the plot to a png
png
2

Try again for another month - say 1999 02 AND again 2014 06
This time extract the values for all points and then subset
strt <- Sys.time() #get the start time
xy <- testbglist[ ,c("longitude_","latitude_m")] # This is to tell R where the coordinates are. Note that the column order needs to be longitude, latitude
testbglistsp <- SpatialPointsDataFrame(coords = xy, data = testbglist, proj4string = CRS("+proj=aea +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-60 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs")) # The CRS is used here is for the albers equal area projection.
netcdf_list <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = TRUE) #true means the full path is included
no_netcdf <- length(netcdf_list) #for the loop - need to know how many files to cycle through
netcdf_name <- list.files("../data/bktstncdf", pattern = '*.nc', full.names = FALSE) #false means the path is not included
aea <- raster("../output/env/aea.tif")
yr <- 1999 # a variable for the observation year
mth <- 02 # a variable for the observation month
for (i in 1:no_netcdf) {
print(netcdf_name[i]) #this just prints the name of the netCDF R is working one
brkyr <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 1)) # extracting the first part of the netcdf filename (which is the year)
brkmth <- as.integer(sapply(strsplit(netcdf_name[i], "_"), "[[", 2)) # extracting the second part of the netcdf filename (which is the month)
brkvar <- (sapply(strsplit(netcdf_name[i], "_"), "[[", 3)) # extracting the third part of the netcdf (inc.nc)
temp_brick <- brick(netcdf_list[i], lvar = 4)
temp_brick <- projectRaster(temp_brick, aea)
for (j in 1:nrow(testbglistsp)) {
de <- testbglistsp$depthlayerno[[j]] # a variable for the observation depth layer
if (brkyr == yr & brkmth == mth & brkvar == "temp.nc"){
testbglistsp$temp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$temp_depth[j] <- NA
} else
testbglistsp$temp_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "salinity.nc") {
testbglistsp$salinity_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$salinity_depth[j] <- NA
} else
testbglistsp$salinity_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "chl.nc") {
testbglistsp$chl_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$chl_depth[j] <- NA
} else
testbglistsp$chl_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "o2.nc") {
testbglistsp$o2_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
if (is.na(de)){
testbglistsp$o2_depth[j] <- NA
} else
testbglistsp$o2_depth[j] <- extract(x=temp_brick[[de]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "mlp.nc") {
testbglistsp$mlp_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
} else if (brkyr == yr & brkmth == mth & brkvar == "ssh.nc") {
testbglistsp$ssh_surface[j] <- extract(x=temp_brick[[1]], y = testbglistsp[j, ])
}
}
}
[1] "1999_02_chl.nc"
[1] "1999_02_mlp.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_o2.nc"
[1] "1999_02_salinity.nc"
[1] "1999_02_ssh.nc"
no non-missing arguments to min; returning Infno non-missing arguments to max; returning -Inf
[1] "1999_02_temp.nc"
write.csv(testbglistsp, "../data/env/background_point_check/1999_02/testbglistoutput.csv", row.names = FALSE)
#test_back_df <- as.data.frame(testbk100000sp)
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.277501 hours
ok now create the first lot of random for 1999_02
testbk100001999 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200001999 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300001999 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500001999 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000001999 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900001999 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100001999, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_ssh_back.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_mlp.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_temp_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_temp_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_salinity_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_salinity_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_chl_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_chl_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_o2_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100001999, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200001999 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500001999 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000001999 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900001999 , na.rm = TRUE, colour = "pink")
dev.copy(png,".../output/env/background_point_check/199902_o2_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
And now 2014_06
#head(test_back_df)
print(Sys.time()-strt) #time it took to run
Time difference of 3.455486 hours
ok now create the first lot of random for 2014_06
testbk100002014 <- test_back_df[sample(nrow(test_back_df), 10000), ] #where 10000 = number of rows to sample (large sample as per maxent)
testbk200002014 <- test_back_df[sample(nrow(test_back_df), 20000), ]
testbk300002014 <- test_back_df[sample(nrow(test_back_df), 30000), ]
testbk500002014 <- test_back_df[sample(nrow(test_back_df), 50000), ]
testbk1000002014 <- test_back_df[sample(nrow(test_back_df), 100000), ]
testbk1900002014 <- test_back_df[sample(nrow(test_back_df), 190000), ]
and plot
ggplot(testbk100002014, aes(x = ssh_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_ssh.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = mlp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_mlp.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = temp_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_temp_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = salinity_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_salinity_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = chl_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_chl_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_surface)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_surface.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
ggplot(testbk100002014, aes(x = o2_depth)) + geom_density(na.rm = TRUE, colour = "red") + geom_density(data=testbk200002014 , na.rm = TRUE, colour = "blue") + geom_density(data=testbk500002014 , na.rm = TRUE, colour = "green") + geom_density(data=testbk1000002014 , na.rm = TRUE, colour = "orange") + geom_density(data=testbk1900002014 , na.rm = TRUE, colour = "pink")
dev.copy(png,"../output/env/background_point_check/201406_o2_depth.png") # to automatically save the plot to a png AND show it inline
dev.off() # stops automatic saving of the plot to a png
LS0tDQp0aXRsZTogImJhY2tncm91bmQgcG9pbnRzIC0gaXMgbW9yZSBiZXR0ZXI/Ig0KYXV0aG9yOiAiU2FtYW50aGEgQW5kcmV3cyINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6IA0KZWRpdG9yX29wdGlvbnM6IA0KICBjaHVua19vdXRwdXRfdHlwZTogaW5saW5lDQotLS0NCg0KIyBPdmVydmlldw0KcXVpY2sgdGVzdCB0byBzZWUgd2hhdCBoYXBwZW5zIHRvIGRpc3RyaWJ1dGlvbiBvZiBlbnYuIHZhcmlhYmxlcyBpZiBhZGQgbW9yZSBiYWNrZ3JvdW5kIHBvaW50cyAoaXMgMTBrIGVub3VnaCBvciBkbyBJIG5lZWQgbW9yZSkNCg0KQSBub3RlIHRvIGFueW9uZSB3aG8gbWlnaHQgaGFwcGVuIHRvIHN0dW1ibGUgYWNyb3NzIHRoaXMuLi4gSSBhbSBhIGJlZ2lubmVyIGluIFIgYW5kIGhhdmUgaGFkIG5vIGV4cG9zdXJlIHRvIHNpbWlsYXIgbGFuZ3VhZ2VzLiBJIGRvbid0IGtub3cgd2hhdCBJJ20gZG9pbmcuIFRoZSBjb2RlIGhlcmVpbiBpcyB1bmxpa2VseSB0byBiZSBlbGVnYW50IGFuZCB0aGVyZSBhcmUgcHJvYmFibHkgbW9yZSBlZmZpY2llbnQgd2F5cyBvZiBydW5uaW5nIHRoZSBjb2RlLg0KDQpCdWlsdCB3aXRoICdyIGdldFJ2ZXJzaW9uKCknLg0KDQojIFBhY2thZ2UgZGVwZW5kZW5jaWVzDQpZb3UgY2FuIGxvYWQgdGhlbSB1c2luZyB0aGUgZm9sbG93aW5nIGNvZGUgd2hpY2ggdXNlcyBhIGZ1bmN0aW9uIGNhbGxlZCBbaXBha10oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vc3RldmVud29ydGhpbmd0b24vMzE3ODE2MykuIA0KTm90ZSB0aGlzIGZ1bmN0aW9uIGNoZWNrcyB0byBzZWUgaWYgdGhlIHBhY2thZ2VzIGFyZSBpbnN0YWxsZWQgZmlyc3QuDQpUaGUgImluY2x1ZGU9RkFMU0UiIHN1cHJlc3NlcyB0aGUgcGFja2FnZSBpbnN0YWxsYXRpb24gdGV4dCBhcHBlYXJpbmcgaW4gdGhlIGRvY3VtZW50Li4uDQpgYGB7ciBwcmUtaW5zdGFsbCBwYWNrYWdlcywgaW5jbHVkZT1GQUxTRX0NCnBhY2thZ2VzIDwtIGMoIm5jZGY0IiwgInJhc3RlciIsICJnZ3Bsb3QyIiwgInBsb3RseSIpIA0Kc291cmNlKCIuLi9zcmMvaXBhay5SIikNCmlwYWsocGFja2FnZXMpDQpgYGANCg0KbG9hZCB0aGUgcmF3IGJhY2tncm91bmQuY3N2IGZpbGUgd2l0aCBhbGwgcG9pbnRzIHRvIHJhbmRvbWx5IGV4dHJhY3QgcG9pbnRzIGZyb20gKC4uL291dHB1dC9lbnYvdW5pcXVlX2NlbGxfY2VudHJvaWRfbG9ubGF0X25hZm8yX2RlcHRoLmNzdikNCg0KYGBge3J9DQp0ZXN0YmdsaXN0IDwtIHJlYWQuY3N2KCIuLi9vdXRwdXQvZW52L3VuaXF1ZV9jZWxsX2NlbnRyb2lkX2xvbmxhdF9uYWZvMl9kZXB0aC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KaGVhZCh0ZXN0YmdsaXN0KQ0KYGBgDQoNCmBgYHtyfQ0KYmFja29ic25vIDwtIG5yb3codGVzdGJnbGlzdCkNCmJhY2tvYnNubw0KYGBgDQoNCg0KDQojIHRoZSBpbmVmZmljZW50IGxvb3ANCg0KDQoNClRoaXMgbG9vcCBydW5zIHRocm91Z2ggdGhlIG5ldGNkZiBmaWxlcyBhbmQgdGhlbiBsb29rcyBmb3Igd2hpY2ggcm93cyBpbiBkYXRhX2FlYSBpdCBzaG91bGQgZXh0cmFjdCB0aGUgdmFsdWUgdG8gcG9pbnQgZnJvbSwgYW5kIGF0IHdoYXQgZGVwdGggKG5ldGNERiBsYXllcikNCg0KU3RhcnQgd2l0aCAyMDA3XzEwIGRhdGENCg0KYGBge3J9DQpzdHJ0IDwtIFN5cy50aW1lKCkgI2dldCB0aGUgc3RhcnQgdGltZQ0KDQp4eSA8LSB0ZXN0YmdsaXN0WyAsYygibG9uZ2l0dWRlXyIsImxhdGl0dWRlX20iKV0gIyBUaGlzIGlzIHRvIHRlbGwgUiB3aGVyZSB0aGUgY29vcmRpbmF0ZXMgYXJlLiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBvcmRlciBuZWVkcyB0byBiZSBsb25naXR1ZGUsIGxhdGl0dWRlDQp0ZXN0YmdsaXN0c3AgPC0gU3BhdGlhbFBvaW50c0RhdGFGcmFtZShjb29yZHMgPSB4eSwgZGF0YSA9IHRlc3RiZ2xpc3QsIHByb2o0c3RyaW5nID0gQ1JTKCIrcHJvaj1hZWEgK2xhdF8xPTUwICtsYXRfMj03MCArbGF0XzA9NDAgK2xvbl8wPS02MCAreF8wPTAgK3lfMD0wICtlbGxwcz1HUlM4MCArZGF0dW09TkFEODMgK3VuaXRzPW0gK25vX2RlZnMiKSkgIyBUaGUgQ1JTIGlzIHVzZWQgaGVyZSBpcyBmb3IgdGhlIGFsYmVycyBlcXVhbCBhcmVhIHByb2plY3Rpb24uDQoNCg0KbmV0Y2RmX2xpc3QgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9ia3RzdG5jZGYiLCBwYXR0ZXJuID0gJyoubmMnLCBmdWxsLm5hbWVzID0gVFJVRSkgI3RydWUgbWVhbnMgdGhlIGZ1bGwgcGF0aCBpcyBpbmNsdWRlZA0Kbm9fbmV0Y2RmIDwtIGxlbmd0aChuZXRjZGZfbGlzdCkgI2ZvciB0aGUgbG9vcCAtIG5lZWQgdG8ga25vdyBob3cgbWFueSBmaWxlcyB0byBjeWNsZSB0aHJvdWdoDQpuZXRjZGZfbmFtZSA8LSBsaXN0LmZpbGVzKCIuLi9kYXRhL2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBGQUxTRSkgI2ZhbHNlIG1lYW5zIHRoZSBwYXRoIGlzIG5vdCBpbmNsdWRlZA0KYWVhIDwtIHJhc3RlcigiLi4vb3V0cHV0L2Vudi9hZWEudGlmIikgDQp5ciA8LSAyMDA3ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiB5ZWFyDQptdGggPC0gMTAgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIG1vbnRoDQoNCmZvciAoaSBpbiAxOm5vX25ldGNkZikgeyAgDQogIHByaW50KG5ldGNkZl9uYW1lW2ldKSAjdGhpcyBqdXN0IHByaW50cyB0aGUgbmFtZSBvZiB0aGUgbmV0Q0RGIFIgaXMgd29ya2luZyBvbmUNCiAgYnJreXIgPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDEpKSAjIGV4dHJhY3RpbmcgdGhlIGZpcnN0IHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIHllYXIpDQogIGJya210aCA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMikpICMgZXh0cmFjdGluZyB0aGUgc2Vjb25kIHBhcnQgb2YgdGhlIG5ldGNkZiBmaWxlbmFtZSAod2hpY2ggaXMgdGhlIG1vbnRoKQ0KICBicmt2YXIgPC0gKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMykpICMgZXh0cmFjdGluZyB0aGUgdGhpcmQgcGFydCBvZiB0aGUgbmV0Y2RmIChpbmMubmMpDQogIHRlbXBfYnJpY2sgPC0gYnJpY2sobmV0Y2RmX2xpc3RbaV0sIGx2YXIgPSA0KQ0KICB0ZW1wX2JyaWNrIDwtIHByb2plY3RSYXN0ZXIodGVtcF9icmljaywgYWVhKSANCiAgICBmb3IgKGogaW4gMTpucm93KHRlc3RiazE5MDAwMHNwKSkgeyAgDQogICAgICBkZSA8LSB0ZXN0YmsxOTAwMDBzcCRkZXB0aGxheWVybm9bW2pdXSAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gZGVwdGggbGF5ZXINCiAgICAgICAgICBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJ0ZW1wLm5jIil7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJHRlbXBfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJrMTkwMDAwc3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJHRlbXBfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCR0ZW1wX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJrMTkwMDAwc3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic2FsaW5pdHkubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJHNhbGluaXR5X3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJHNhbGluaXR5X2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJrMTkwMDAwc3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gImNobC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkY2hsX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRjaGxfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRjaGxfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmsxOTAwMDBzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAibzIubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJG8yX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmsxOTAwMDBzcCRvMl9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiazE5MDAwMHNwJG8yX2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJrMTkwMDAwc3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm1scC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3AkbWxwX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gInNzaC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJrMTkwMDAwc3Akc3NoX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiazE5MDAwMHNwW2osIF0pIA0KICAgICAgICAgICAgDQogICAgICAgICAgfQ0KICAgICANCiAgICB9DQp9DQp3cml0ZS5jc3YodGVzdGJnbGlzdHNwLCAiLi4vZGF0YS9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfYWxsYmFja2dyb3VuZHBvaW50cy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCnRlc3RfYmFja19kZiA8LSBhcy5kYXRhLmZyYW1lKHRlc3RiZ2xpc3RzcCkNCnByaW50KFN5cy50aW1lKCktc3RydCkgI3RpbWUgaXQgdG9vayB0byBydW4NCmBgYA0KDQpvayBub3cgY3JlYXRlIHRoZSBmaXJzdCBsb3Qgb2YgcmFuZG9tIGZvciAyMDA3XzEwDQoNCmBgYHtyfQ0KdGVzdGJrMTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMCksIF0gICN3aGVyZSAxMDAwMCA9IG51bWJlciBvZiByb3dzIHRvIHNhbXBsZSAobGFyZ2Ugc2FtcGxlIGFzIHBlciBtYXhlbnQpDQp0ZXN0YmsyMDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDIwMDAwKSwgXSAgDQp0ZXN0YmszMDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDMwMDAwKSwgXSAgDQp0ZXN0Yms1MDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDUwMDAwKSwgXSAgDQp0ZXN0YmsxMDAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxMDAwMDApLCBdICANCnRlc3RiazE5MDAwMDE5OTkgPC0gdGVzdF9iYWNrX2RmW3NhbXBsZShucm93KHRlc3RfYmFja19kZiksIDE5MDAwMCksIF0gIA0KYGBgDQoNCg0KDQpwbG90IGVhY2ggdmFyaWFibGUgYWdhaW5zdCB0aGUgZGlmZmVyZW50IG5vIG9mIGJhY2tncm91bmQgcG9pbnRzDQoNCg0KDQpgYGB7cn0NCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gc3NoX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfc3NoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfbWxwX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gdGVtcF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3RlbXBfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHRlbXBfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfdGVtcF9kZXB0aF9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfc2FsaW5pdHlfc3VyZmFjZV9iYWNrX25vLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdDEwMDAwLCBhZXMoeCA9IHNhbGluaXR5X2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MjAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0NTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDEwMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDE5MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMjAwNzEwX3NhbGluaXR5X2RlcHRoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gY2hsX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfY2hsX3N1cmZhY2VfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3QxMDAwMCwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfY2hsX2RlcHRoX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gbzJfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDIwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdDUwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxMDAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QxOTAwMDAgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMDcxMF9vMl9zdXJmYWNlX2JhY2tfbm8ucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0MTAwMDAsIGFlcyh4ID0gbzJfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3QyMDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3Q1MDAwMCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTAwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0MTkwMDAwICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDA3MTBfbzJfZGVwdGhfYmFja19uby5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQpUcnkgYWdhaW4gZm9yIGFub3RoZXIgbW9udGggLSBzYXkgMTk5OSAwMiBBTkQgYWdhaW4gMjAxNCAwNg0KDQpUaGlzIHRpbWUgZXh0cmFjdCB0aGUgdmFsdWVzIGZvciBhbGwgcG9pbnRzIGFuZCB0aGVuIHN1YnNldA0KDQpgYGB7cn0NCnN0cnQgPC0gU3lzLnRpbWUoKSAjZ2V0IHRoZSBzdGFydCB0aW1lDQoNCnh5IDwtIHRlc3RiZ2xpc3RbICxjKCJsb25naXR1ZGVfIiwibGF0aXR1ZGVfbSIpXSAjIFRoaXMgaXMgdG8gdGVsbCBSIHdoZXJlIHRoZSBjb29yZGluYXRlcyBhcmUuIE5vdGUgdGhhdCB0aGUgY29sdW1uIG9yZGVyIG5lZWRzIHRvIGJlIGxvbmdpdHVkZSwgbGF0aXR1ZGUNCnRlc3RiZ2xpc3RzcCA8LSBTcGF0aWFsUG9pbnRzRGF0YUZyYW1lKGNvb3JkcyA9IHh5LCBkYXRhID0gdGVzdGJnbGlzdCwgcHJvajRzdHJpbmcgPSBDUlMoIitwcm9qPWFlYSArbGF0XzE9NTAgK2xhdF8yPTcwICtsYXRfMD00MCArbG9uXzA9LTYwICt4XzA9MCAreV8wPTAgK2VsbHBzPUdSUzgwICtkYXR1bT1OQUQ4MyArdW5pdHM9bSArbm9fZGVmcyIpKSAjIFRoZSBDUlMgaXMgdXNlZCBoZXJlIGlzIGZvciB0aGUgYWxiZXJzIGVxdWFsIGFyZWEgcHJvamVjdGlvbi4NCg0KDQpuZXRjZGZfbGlzdCA8LSBsaXN0LmZpbGVzKCIuLi9kYXRhL2JrdHN0bmNkZiIsIHBhdHRlcm4gPSAnKi5uYycsIGZ1bGwubmFtZXMgPSBUUlVFKSAjdHJ1ZSBtZWFucyB0aGUgZnVsbCBwYXRoIGlzIGluY2x1ZGVkDQpub19uZXRjZGYgPC0gbGVuZ3RoKG5ldGNkZl9saXN0KSAjZm9yIHRoZSBsb29wIC0gbmVlZCB0byBrbm93IGhvdyBtYW55IGZpbGVzIHRvIGN5Y2xlIHRocm91Z2gNCm5ldGNkZl9uYW1lIDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IEZBTFNFKSAjZmFsc2UgbWVhbnMgdGhlIHBhdGggaXMgbm90IGluY2x1ZGVkDQphZWEgPC0gcmFzdGVyKCIuLi9vdXRwdXQvZW52L2FlYS50aWYiKSANCnlyIDwtIDE5OTkgICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIHllYXINCm10aCA8LSAwMiAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gbW9udGgNCg0KZm9yIChpIGluIDE6bm9fbmV0Y2RmKSB7ICANCiAgcHJpbnQobmV0Y2RmX25hbWVbaV0pICN0aGlzIGp1c3QgcHJpbnRzIHRoZSBuYW1lIG9mIHRoZSBuZXRDREYgUiBpcyB3b3JraW5nIG9uZQ0KICBicmt5ciA8LSBhcy5pbnRlZ2VyKHNhcHBseShzdHJzcGxpdChuZXRjZGZfbmFtZVtpXSwgIl8iKSwgIltbIiwgMSkpICMgZXh0cmFjdGluZyB0aGUgZmlyc3QgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgeWVhcikNCiAgYnJrbXRoIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAyKSkgIyBleHRyYWN0aW5nIHRoZSBzZWNvbmQgcGFydCBvZiB0aGUgbmV0Y2RmIGZpbGVuYW1lICh3aGljaCBpcyB0aGUgbW9udGgpDQogIGJya3ZhciA8LSAoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAzKSkgIyBleHRyYWN0aW5nIHRoZSB0aGlyZCBwYXJ0IG9mIHRoZSBuZXRjZGYgKGluYy5uYykNCiAgdGVtcF9icmljayA8LSBicmljayhuZXRjZGZfbGlzdFtpXSwgbHZhciA9IDQpDQogIHRlbXBfYnJpY2sgPC0gcHJvamVjdFJhc3Rlcih0ZW1wX2JyaWNrLCBhZWEpIA0KICAgIGZvciAoaiBpbiAxOm5yb3codGVzdGJnbGlzdHNwKSkgeyAgDQogICAgICBkZSA8LSB0ZXN0YmdsaXN0c3AkZGVwdGhsYXllcm5vW1tqXV0gICMgYSB2YXJpYWJsZSBmb3IgdGhlIG9ic2VydmF0aW9uIGRlcHRoIGxheWVyDQogICAgICAgICAgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAidGVtcC5uYyIpew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic2FsaW5pdHkubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzYWxpbml0eV9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAiY2hsLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm8yLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbzJfZGVwdGhbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbW2RlXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgfSBlbHNlIGlmIChicmt5ciA9PSB5ciAmIGJya210aCA9PSBtdGggJiBicmt2YXIgPT0gIm1scC5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJG1scF9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkNCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAic3NoLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3Akc3NoX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgIA0KICAgICAgICAgIH0NCiAgICAgDQogICAgfQ0KfQ0Kd3JpdGUuY3N2KHRlc3RiZ2xpc3RzcCwgIi4uL2RhdGEvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX2FsbGJhY2tncm91bmRwb2ludHMuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQp0ZXN0X2JhY2tfZGYgPC0gYXMuZGF0YS5mcmFtZSh0ZXN0YmdsaXN0c3ApDQpwcmludChTeXMudGltZSgpLXN0cnQpICN0aW1lIGl0IHRvb2sgdG8gcnVuDQpgYGANCg0Kb2sgbm93IGNyZWF0ZSB0aGUgZmlyc3QgbG90IG9mIHJhbmRvbSBmb3IgMTk5OV8wMg0KDQpgYGB7cn0NCnRlc3RiazEwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAyMDAwMCksIF0gIA0KdGVzdGJrMzAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAzMDAwMCksIF0gIA0KdGVzdGJrNTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCA1MDAwMCksIF0gIA0KdGVzdGJrMTAwMDAwMTk5OSA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAxOTk5IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxOTAwMDApLCBdICANCmBgYA0KDQphbmQgcGxvdA0KDQoNCmBgYHtyfQ0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBzc2hfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8xOTk5MDJfc3NoX2JhY2sucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX21scC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3RlbXBfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSB0ZW1wX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl90ZW1wX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDE5OTksIGFlcyh4ID0gc2FsaW5pdHlfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX3NhbGluaXR5X2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IGNobF9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9jaGxfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAxOTk5ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uLi9vdXRwdXQvZW52L2JhY2tncm91bmRfcG9pbnRfY2hlY2svMTk5OTAyX2NobF9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMTk5OSwgYWVzKHggPSBvMl9zdXJmYWNlKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9vMl9zdXJmYWNlLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAxOTk5LCBhZXMoeCA9IG8yX2RlcHRoKSkgKyBnZW9tX2RlbnNpdHkobmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicmVkIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsyMDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJibHVlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0Yms1MDAwMDE5OTkgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJncmVlbiIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTAwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gIm9yYW5nZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMTkwMDAwMTk5OSAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gInBpbmsiKQ0KZGV2LmNvcHkocG5nLCIuLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzE5OTkwMl9vMl9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCkFuZCBub3cgMjAxNF8wNg0KDQoNCmBgYHtyfQ0Kc3RydCA8LSBTeXMudGltZSgpICNnZXQgdGhlIHN0YXJ0IHRpbWUNCg0KeHkgPC0gdGVzdGJnbGlzdFsgLGMoImxvbmdpdHVkZV8iLCJsYXRpdHVkZV9tIildICMgVGhpcyBpcyB0byB0ZWxsIFIgd2hlcmUgdGhlIGNvb3JkaW5hdGVzIGFyZS4gTm90ZSB0aGF0IHRoZSBjb2x1bW4gb3JkZXIgbmVlZHMgdG8gYmUgbG9uZ2l0dWRlLCBsYXRpdHVkZQ0KdGVzdGJnbGlzdHNwIDwtIFNwYXRpYWxQb2ludHNEYXRhRnJhbWUoY29vcmRzID0geHksIGRhdGEgPSB0ZXN0YmdsaXN0LCBwcm9qNHN0cmluZyA9IENSUygiK3Byb2o9YWVhICtsYXRfMT01MCArbGF0XzI9NzAgK2xhdF8wPTQwICtsb25fMD0tNjAgK3hfMD0wICt5XzA9MCArZWxscHM9R1JTODAgK2RhdHVtPU5BRDgzICt1bml0cz1tICtub19kZWZzIikpICMgVGhlIENSUyBpcyB1c2VkIGhlcmUgaXMgZm9yIHRoZSBhbGJlcnMgZXF1YWwgYXJlYSBwcm9qZWN0aW9uLg0KDQoNCm5ldGNkZl9saXN0IDwtIGxpc3QuZmlsZXMoIi4uL2RhdGEvYmt0c3RuY2RmIiwgcGF0dGVybiA9ICcqLm5jJywgZnVsbC5uYW1lcyA9IFRSVUUpICN0cnVlIG1lYW5zIHRoZSBmdWxsIHBhdGggaXMgaW5jbHVkZWQNCm5vX25ldGNkZiA8LSBsZW5ndGgobmV0Y2RmX2xpc3QpICNmb3IgdGhlIGxvb3AgLSBuZWVkIHRvIGtub3cgaG93IG1hbnkgZmlsZXMgdG8gY3ljbGUgdGhyb3VnaA0KbmV0Y2RmX25hbWUgPC0gbGlzdC5maWxlcygiLi4vZGF0YS9ia3RzdG5jZGYiLCBwYXR0ZXJuID0gJyoubmMnLCBmdWxsLm5hbWVzID0gRkFMU0UpICNmYWxzZSBtZWFucyB0aGUgcGF0aCBpcyBub3QgaW5jbHVkZWQNCmFlYSA8LSByYXN0ZXIoIi4uL291dHB1dC9lbnYvYWVhLnRpZiIpIA0KeXIgPC0gMjAxNCAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24geWVhcg0KbXRoIDwtIDA2ICAjIGEgdmFyaWFibGUgZm9yIHRoZSBvYnNlcnZhdGlvbiBtb250aA0KDQpmb3IgKGkgaW4gMTpub19uZXRjZGYpIHsgIA0KICBwcmludChuZXRjZGZfbmFtZVtpXSkgI3RoaXMganVzdCBwcmludHMgdGhlIG5hbWUgb2YgdGhlIG5ldENERiBSIGlzIHdvcmtpbmcgb25lDQogIGJya3lyIDwtIGFzLmludGVnZXIoc2FwcGx5KHN0cnNwbGl0KG5ldGNkZl9uYW1lW2ldLCAiXyIpLCAiW1siLCAxKSkgIyBleHRyYWN0aW5nIHRoZSBmaXJzdCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSB5ZWFyKQ0KICBicmttdGggPC0gYXMuaW50ZWdlcihzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDIpKSAjIGV4dHJhY3RpbmcgdGhlIHNlY29uZCBwYXJ0IG9mIHRoZSBuZXRjZGYgZmlsZW5hbWUgKHdoaWNoIGlzIHRoZSBtb250aCkNCiAgYnJrdmFyIDwtIChzYXBwbHkoc3Ryc3BsaXQobmV0Y2RmX25hbWVbaV0sICJfIiksICJbWyIsIDMpKSAjIGV4dHJhY3RpbmcgdGhlIHRoaXJkIHBhcnQgb2YgdGhlIG5ldGNkZiAoaW5jLm5jKQ0KICB0ZW1wX2JyaWNrIDwtIGJyaWNrKG5ldGNkZl9saXN0W2ldLCBsdmFyID0gNCkNCiAgdGVtcF9icmljayA8LSBwcm9qZWN0UmFzdGVyKHRlbXBfYnJpY2ssIGFlYSkgDQogICAgZm9yIChqIGluIDE6bnJvdyh0ZXN0YmdsaXN0c3ApKSB7ICANCiAgICAgIGRlIDwtIHRlc3RiZ2xpc3RzcCRkZXB0aGxheWVybm9bW2pdXSAgIyBhIHZhcmlhYmxlIGZvciB0aGUgb2JzZXJ2YXRpb24gZGVwdGggbGF5ZXINCiAgICAgICAgICBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJ0ZW1wLm5jIil7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCR0ZW1wX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHRlbXBfZGVwdGhbal0gPC0gTkENCiAgICAgICAgICAgICAgfSBlbHNlICANCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkdGVtcF9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJzYWxpbml0eS5uYyIpIHsNCiAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICAgICAgaWYgKGlzLm5hKGRlKSl7DQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJHNhbGluaXR5X2RlcHRoW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1tkZV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJjaGwubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRjaGxfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgICBpZiAoaXMubmEoZGUpKXsNCiAgICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkY2hsX2RlcHRoW2pdIDwtIE5BDQogICAgICAgICAgICAgIH0gZWxzZSAgDQogICAgICAgICAgICAgICAgdGVzdGJnbGlzdHNwJGNobF9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAibzIubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9zdXJmYWNlW2pdIDwtIGV4dHJhY3QoeD10ZW1wX2JyaWNrW1sxXV0sIHkgPSB0ZXN0YmdsaXN0c3BbaiwgXSkgDQogICAgICAgICAgICAgIGlmIChpcy5uYShkZSkpew0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9kZXB0aFtqXSA8LSBOQQ0KICAgICAgICAgICAgICB9IGVsc2UgIA0KICAgICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRvMl9kZXB0aFtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbZGVdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKSANCiAgICAgICAgICB9IGVsc2UgaWYgKGJya3lyID09IHlyICYgYnJrbXRoID09IG10aCAmIGJya3ZhciA9PSAibWxwLm5jIikgew0KICAgICAgICAgICAgICB0ZXN0YmdsaXN0c3AkbWxwX3N1cmZhY2Vbal0gPC0gZXh0cmFjdCh4PXRlbXBfYnJpY2tbWzFdXSwgeSA9IHRlc3RiZ2xpc3RzcFtqLCBdKQ0KICAgICAgICAgIH0gZWxzZSBpZiAoYnJreXIgPT0geXIgJiBicmttdGggPT0gbXRoICYgYnJrdmFyID09ICJzc2gubmMiKSB7DQogICAgICAgICAgICAgIHRlc3RiZ2xpc3RzcCRzc2hfc3VyZmFjZVtqXSA8LSBleHRyYWN0KHg9dGVtcF9icmlja1tbMV1dLCB5ID0gdGVzdGJnbGlzdHNwW2osIF0pIA0KICAgICAgICAgICAgDQogICAgICAgICAgfQ0KICAgICANCiAgICB9DQp9DQp3cml0ZS5jc3YodGVzdGJnbGlzdHNwLCAiLi4vZGF0YS9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfYWxsYmFja2dyb3VuZHBvaW50cy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCnRlc3RfYmFja19kZiA8LSBhcy5kYXRhLmZyYW1lKHRlc3RiZ2xpc3RzcCkNCnByaW50KFN5cy50aW1lKCktc3RydCkgI3RpbWUgaXQgdG9vayB0byBydW4NCmBgYA0Kb2sgbm93IGNyZWF0ZSB0aGUgZmlyc3QgbG90IG9mIHJhbmRvbSBmb3IgMjAxNF8wNg0KDQpgYGB7cn0NCnRlc3RiazEwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDApLCBdICAjd2hlcmUgMTAwMDAgPSBudW1iZXIgb2Ygcm93cyB0byBzYW1wbGUgKGxhcmdlIHNhbXBsZSBhcyBwZXIgbWF4ZW50KQ0KdGVzdGJrMjAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAyMDAwMCksIF0gIA0KdGVzdGJrMzAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAzMDAwMCksIF0gIA0KdGVzdGJrNTAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCA1MDAwMCksIF0gIA0KdGVzdGJrMTAwMDAwMjAxNCA8LSB0ZXN0X2JhY2tfZGZbc2FtcGxlKG5yb3codGVzdF9iYWNrX2RmKSwgMTAwMDAwKSwgXSAgDQp0ZXN0YmsxOTAwMDAyMDE0IDwtIHRlc3RfYmFja19kZltzYW1wbGUobnJvdyh0ZXN0X2JhY2tfZGYpLCAxOTAwMDApLCBdICANCmBgYA0KDQphbmQgcGxvdA0KDQoNCmBgYHtyfQ0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBzc2hfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zc2gucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gbWxwX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfbWxwLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHRlbXBfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl90ZW1wX3N1cmZhY2UucG5nIikgIyB0byBhdXRvbWF0aWNhbGx5IHNhdmUgdGhlIHBsb3QgdG8gYSBwbmcgQU5EIHNob3cgaXQgaW5saW5lDQpkZXYub2ZmKCkgIyBzdG9wcyBhdXRvbWF0aWMgc2F2aW5nIG9mIHRoZSBwbG90IHRvIGEgcG5nDQoNCmdncGxvdCh0ZXN0YmsxMDAwMDIwMTQsIGFlcyh4ID0gdGVtcF9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl90ZW1wX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IHNhbGluaXR5X3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfc2FsaW5pdHlfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBzYWxpbml0eV9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9zYWxpbml0eV9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBjaGxfc3VyZmFjZSkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9jaGxfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBjaGxfZGVwdGgpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfY2hsX2RlcHRoLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpnZ3Bsb3QodGVzdGJrMTAwMDAyMDE0LCBhZXMoeCA9IG8yX3N1cmZhY2UpKSArIGdlb21fZGVuc2l0eShuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJyZWQiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazIwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImJsdWUiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazUwMDAwMjAxNCAsIG5hLnJtID0gVFJVRSwgY29sb3VyID0gImdyZWVuIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxMDAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAib3JhbmdlIikgKyBnZW9tX2RlbnNpdHkoZGF0YT10ZXN0YmsxOTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAicGluayIpDQpkZXYuY29weShwbmcsIi4uL291dHB1dC9lbnYvYmFja2dyb3VuZF9wb2ludF9jaGVjay8yMDE0MDZfbzJfc3VyZmFjZS5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCg0KZ2dwbG90KHRlc3RiazEwMDAwMjAxNCwgYWVzKHggPSBvMl9kZXB0aCkpICsgZ2VvbV9kZW5zaXR5KG5hLnJtID0gVFJVRSwgY29sb3VyID0gInJlZCIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrMjAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiYmx1ZSIpICsgZ2VvbV9kZW5zaXR5KGRhdGE9dGVzdGJrNTAwMDAyMDE0ICwgbmEucm0gPSBUUlVFLCBjb2xvdXIgPSAiZ3JlZW4iKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazEwMDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJvcmFuZ2UiKSArIGdlb21fZGVuc2l0eShkYXRhPXRlc3RiazE5MDAwMDIwMTQgLCBuYS5ybSA9IFRSVUUsIGNvbG91ciA9ICJwaW5rIikNCmRldi5jb3B5KHBuZywiLi4vb3V0cHV0L2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrLzIwMTQwNl9vMl9kZXB0aC5wbmciKSAjIHRvIGF1dG9tYXRpY2FsbHkgc2F2ZSB0aGUgcGxvdCB0byBhIHBuZyBBTkQgc2hvdyBpdCBpbmxpbmUNCmRldi5vZmYoKSAjIHN0b3BzIGF1dG9tYXRpYyBzYXZpbmcgb2YgdGhlIHBsb3QgdG8gYSBwbmcNCmBgYA0KDQoNCg0KIyAzZCBwbG90IGJhY2tncm91bmQgcG9pbnRzDQoNCmBgYHtyfQ0KYmNrMjAxNF8wNl8zZCA8LSBwbG90X2x5KHg9IHRlc3RiazEwMDAwMjAxNCRsb25naXR1ZGVfLCB5ID0gdGVzdGJrMTAwMDAyMDE0JGxhdGl0dWRlX20sIHogPSB0ZXN0YmsxMDAwMDIwMTQkZGVwdGhsYXllcm5vKQ0KYmNrMjAxNF8wNl8zZA0KYGBgDQoNCiMgMmQgcGxvdCBiYWNrZ3JvdW5kIHBvaW50cw0KDQpgYGB7cn0NCmJjazIwMTRfMDZfMmQgPC0gcGxvdCh4PSB0ZXN0YmsxMDAwMDIwMTQkbG9uZ2l0dWRlXywgeSA9IHRlc3RiazEwMDAwMjAxNCRsYXRpdHVkZV9tKQ0KZGV2LmNvcHkocG5nLCIuLi9kYXRhL2Vudi9iYWNrZ3JvdW5kX3BvaW50X2NoZWNrL2JjazEwMDAwXzJkLnBuZyIpICMgdG8gYXV0b21hdGljYWxseSBzYXZlIHRoZSBwbG90IHRvIGEgcG5nIEFORCBzaG93IGl0IGlubGluZQ0KZGV2Lm9mZigpICMgc3RvcHMgYXV0b21hdGljIHNhdmluZyBvZiB0aGUgcGxvdCB0byBhIHBuZw0KDQpgYGA=